import type { LogEntry } from '../../lib/logger'
import type { IUserCenterModule } from '../../types/interfaces'
import { CollapsiblePanel } from '../../components/collapsible_panel'
import { SystemInfo } from '../../lib/system_info'
import { DownloadFileMimeType } from '../../lib/utils/browser/file'
import { ToolKit } from '../../lib/utils/toolkit'
import { CommonUtils } from '../../menu/common'
import {
  AppStyleCollections,
  BodyAttrs,
  BodyClasses,
  BUTTON_TEMPLATE,
  BUTTON_TEMPLATE_STYLES,
  CustomElementStyleId,
  getCurrentHostname,
  getCurrentURL,
  logger,
  PROJECT_PREFIX,
} from '../../types/constants'
import { SYMBOLS } from '../../types/interfaces'

export interface EnvironmentInfo {
  systemInfo: SystemInfoData
  pageinfo: PageInfo
  personalizationInfo: PersonalizationInfo
  platformInfo: PlatformInfo
  scriptInfo: ScriptInfo
  viewportInfo: ViewportInfo
}

export interface SystemInfoData {
  os: string
  browser: {
    fullName: string
    handlerFullName: string
  }
}

export interface PageInfo {
  hostname: string
  url: string
  pageType: string
  rootFontSize: string
}

export interface PersonalizationInfo {
  theme: string
  hasWallpaper: boolean
  customHide: boolean
  customCss: () => boolean
  customJs: () => boolean
}

export interface PlatformInfo {
  isLoggedIn: boolean | undefined
}

export interface ScriptInfo {
  name: string
  version: string
}

export interface ViewportInfo {
  width: number
  height: number
  description: string
}

export class Feedback implements IUserCenterModule {
  name: string = 'Feedback'
  private utils: CommonUtils
  private feedbackPanel: CollapsiblePanel
  private static instance: Feedback

  constructor() {
    this.utils = new CommonUtils()
    this.feedbackPanel = new CollapsiblePanel({
      id: 'feedback-tips',
      type: 'hint',
      title: '反馈要求',
      content: this.renderFeedbackTips(),
    })
  }

  get className(): string {
    return 'feed-back-container'
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): Feedback {
    if (!Feedback.instance) {
      Feedback.instance = new Feedback()
    }
    return Feedback.instance
  }

  public generateHTML(): string {
    return `
      <div class="${this.className}">
        <div class="feedback-header">
          ${BUTTON_TEMPLATE.download('download-logs-btn', '下载日志')}
        </div>
        ${this.feedbackPanel.render()}
        ${this.renderFeedbackSteps()}
      </div>
    `
  }

  private renderFeedbackTips(): string {
    return `
      <ul class="feedback-tips-list">
        <li>${SYMBOLS.OTHERS.BUG} 反馈使用中遇到的问题时，尽可能提供比较详细的问题清单，包括：问题类型（如：功能错误、界面问题等）、问题描述、复现详细步骤、期望结果，并附加相关截图；
            如果有其他相关信息（如：是否是登录状态、浏览器控制台有该脚本打印的错误日志），请一并提供；
        </li>
        <li>${SYMBOLS.OTHERS.BRAIN} 如果对当前脚本有优化改进想法时，为了更高效地进行，请提供：使用场景（您通常在什么场景下需要此功能）、当前痛点（当前版本有哪些使用上的不便）、预期方案（您希望如何改进这个功能）等关键要素。</li>
      </ul>
    `
  }

  private renderFeedbackSteps(): string {
    return `
      <div class="feedback-steps-content">
        ${SYMBOLS.STATUS.NOTIFICATION}
        ${this.utils.formatInfo('反馈问题时，请下载并核对日志信息', 'primary')}
        ${this.utils.formatInfo('（如果部分存在未知描述，请手动更新）', 'redHighlight')}
        ，再点击按钮访问反馈页面，并根据反馈要求完善填写内容，以便更好地了解问题并快速定位，减少不必要的沟通成本，感谢您的配合与支持！！！
        ${SYMBOLS.STATUS.CELEBRATION}${SYMBOLS.UI.BEER}
      </div>
    `
  }

  handleOpen(): void {
    const $selector = $(`.${this.className}`)

    this.feedbackPanel.mount($selector)

    // 日志下载点击事件
    $selector.find('#download-logs-btn').on('click', () => {
      this.prepareAndDownloadLogs().catch((e: any) => {
        logger.error('日志下载失败:', e)
      })
    })
  }

  /**
   * 获取完整的环境信息
   */
  getEnvironmentInfo(): EnvironmentInfo {
    const systemInfo = new SystemInfo().getSystemInfo()
    const scriptInfo = GM_info.script

    // 获取视口信息
    const innerWidth = window.innerWidth
    const contentWidth = document.documentElement.clientWidth
    const contentHeight = document.documentElement.clientHeight
    const scrollWidth = innerWidth - contentWidth

    return {
      systemInfo: {
        os: systemInfo.os,
        browser: {
          fullName: systemInfo.browser.fullName,
          handlerFullName: systemInfo.browser.handlerFullName,
        },
      },
      pageinfo: {
        hostname: getCurrentHostname() || '未知',
        url: getCurrentURL() || '未知',
        pageType: document.body.getAttribute(BodyAttrs.PAGE_TYPE) || '未知',
        rootFontSize: `${Number.parseFloat(getComputedStyle(document.documentElement).fontSize)}px`,
      },
      personalizationInfo: {
        theme: ToolKit.browser.theme.getCurrentTheme(),
        hasWallpaper: document.body.classList.contains(AppStyleCollections.Wallpaper.EXISTS),
        customHide: document.body.classList.contains(BodyClasses.HAS_CUSTOM_HIDDEN),
        customCss: () => {
          const styleElement = document.getElementById(CustomElementStyleId.CustomCss)
          return Boolean(styleElement && (styleElement.textContent || '').trim())
        },
        customJs: () => {
          const styleElement = document.getElementById(CustomElementStyleId.CustomJs)
          return Boolean(styleElement && (styleElement.textContent || '').trim())
        },
      },
      platformInfo: {
        isLoggedIn: ToolKit.browser.platform.isLoggedIn(true),
      },
      scriptInfo: {
        name: scriptInfo.name,
        version: scriptInfo.version,
      },
      viewportInfo: {
        width: contentWidth,
        height: contentHeight,
        description: scrollWidth > 0
          ? `（${scrollWidth}px 滚动条）`
          : '（不含滚动条）',
      },
    }
  }

  /**
   * 准备日志数据并触发下载
   */
  private async prepareAndDownloadLogs(): Promise<void> {
    try {
      // 获取环境信息
      const envInfo = this.getEnvironmentInfo()

      // 只获取当前页面的日志
      let runtimeLogs: any[] = []
      try {
        const allLogs = await logger.getCachedLogs()
        runtimeLogs = allLogs.filter(log => log.url === envInfo.pageinfo.url)
      }
      catch (e: any) {
        logger.error('获取运行日志失败:', e)
      }

      // 计算统计信息
      const logStats = this.calculateLogStatistics(runtimeLogs)
      const timeRange = this.calculateLogTimeRange(runtimeLogs)
      const timeRangeText = timeRange
        ? timeRange.start === timeRange.end
          ? `记录时间: ${timeRange.start}`
          : `时间范围: ${timeRange.start} 至 ${timeRange.end}`
        : '时间范围: NA'

      // 构建日志内容
      const logContent = [
        '=============== 基础信息 ===============',
        `生成时间: ${new Date().toLocaleString()}`,
        '',
        '=============== 日志信息 ===============',
        `日志级别: WARN`,
        logger.getClearStrategyDescription(),
        logStats.total > 0 ? `日志条数: ${logStats.total} (WARN: ${logStats.warn}, ERROR: ${logStats.error})` : '日志条数: 0',
        timeRangeText,
        '',
        '=============== 环境信息 ===============',
        `脚本信息: ${envInfo.scriptInfo.name}（v${envInfo.scriptInfo.version}）`,
        `操作系统: ${envInfo.systemInfo.os}`,
        `浏 览 器: ${envInfo.systemInfo.browser.fullName}`,
        `油猴插件: ${envInfo.systemInfo.browser.handlerFullName}`,
        `页面域名: ${envInfo.pageinfo.hostname}`,
        `页面地址: ${envInfo.pageinfo.url}`,
        `页面类型: ${envInfo.pageinfo.pageType}`,
        `根 字 体: ${envInfo.pageinfo.rootFontSize}`,
        `视口尺寸: ${envInfo.viewportInfo.width}×${envInfo.viewportInfo.height}${envInfo.viewportInfo.description}`,
        '',
        '=============== 个 性 化 ===============',
        `页面主题   : ${envInfo.personalizationInfo.theme}`,
        `自定义壁纸 : ${envInfo.personalizationInfo.hasWallpaper ? SYMBOLS.STATUS.SUCCESS : SYMBOLS.STATUS.ERROR}`,
        `自定义隐藏 : ${envInfo.personalizationInfo.customHide ? SYMBOLS.STATUS.SUCCESS : SYMBOLS.STATUS.ERROR}`,
        `自定义CSS  : ${envInfo.personalizationInfo.customCss() ? SYMBOLS.STATUS.SUCCESS : SYMBOLS.STATUS.ERROR}`,
        `自定义JS   : ${envInfo.personalizationInfo.customJs() ? SYMBOLS.STATUS.SUCCESS : SYMBOLS.STATUS.ERROR}`,
        '',
        '=============== 平台信息 ===============',
        `是否登录 : ${envInfo.platformInfo.isLoggedIn === true
          ? SYMBOLS.STATUS.SUCCESS
          : envInfo.platformInfo.isLoggedIn === false
            ? SYMBOLS.STATUS.ERROR
            : '当前版本不支持识别'}`,
        '',
        '=============== 运行日志 ===============',
        runtimeLogs.length > 0
          ? runtimeLogs.map(log => this.formatLogEntry(log)).join('\n')
          : '未获取到异常日志',
      ].join('\n')

      // 创建下载
      ToolKit.browser.file.downloadFile(logContent, {
        filename: `${PROJECT_PREFIX}-日志文件_${ToolKit.time.formatTime(new Date())}.txt`,
        type: DownloadFileMimeType.TEXT_PLAIN,
      })
    }
    catch (e: any) {
      logger.error('生成日志文件失败:', e)
    }
  }

  /**
   * 格式化单个日志条目
   * @param log 日志对象
   * @returns 格式化后的日志字符串
   */
  private formatLogEntry(log: LogEntry): string {
    const parts = [
      `[${log.timestamp}]`,
      `[${log.level}]`,
      log.message,
    ].filter(Boolean) // 移除空值

    let entry = parts.join(' ')

    // 只有当有实际数据时才显示附加数据
    if (log.data && Array.isArray(log.data) && log.data.length > 0) {
      entry += `\n附加数据: ${JSON.stringify(log.data, null, 2)}`
    }
    else if (log.data && typeof log.data === 'object' && Object.keys(log.data).length > 0) {
      entry += `\n附加数据: ${JSON.stringify(log.data, null, 2)}`
    }

    return entry
  }

  /**
   * 计算日志统计信息
   * @param logs 日志数组
   * @returns 包含各级别日志数量的对象
   */
  private calculateLogStatistics(logs: LogEntry[]): {
    total: number
    warn: number
    error: number
  } {
    const stats = {
      total: logs.length,
      warn: 0,
      error: 0,
    }

    logs.forEach((log) => {
      const level = log.level.toLowerCase()
      if (level === 'warn')
        stats.warn++
      else if (level === 'error')
        stats.error++
    })

    return stats
  }

  /**
   * 计算日志时间范围
   * @param logs 日志数组
   * @returns 包含最早和最晚时间戳的对象，如果没有日志则返回null
   */
  private calculateLogTimeRange(logs: LogEntry[]): { start: string, end: string } | null {
    if (!logs || logs.length === 0)
      return null

    // 提取所有时间戳并转换为Date对象
    const timestamps = logs
      .map(log => new Date(log.timestamp).getTime())
      .filter(ts => !Number.isNaN(ts))

    if (timestamps.length === 0)
      return null

    // 找到最早和最晚时间戳
    const minTime = Math.min(...timestamps)
    const maxTime = Math.max(...timestamps)

    // 格式化为本地时间字符串
    const formatOptions: Intl.DateTimeFormatOptions = {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    }

    return {
      start: new Date(minTime).toLocaleString(undefined, formatOptions),
      end: new Date(maxTime).toLocaleString(undefined, formatOptions),
    }
  }

  destroy(): void {
    this.feedbackPanel.destroy()
  }

  /**
   * 样式
   */
  public styles(): string {
    return `/* =============================== 【问题反馈】 =============================== */
      .feed-back-container {
        all: initial !important;
        display: flex;
        gap: 5px;
        flex-direction: column;
        justify-content: left;
        line-height: 1.5 !important;
        
        .feedback-header {
          display: flex;
          align-items: center;
          ${BUTTON_TEMPLATE_STYLES.download}
        }
        
        /* 信息网格布局 */
        .info-grid {
          display: grid;
          grid-template-columns: 1fr;
          gap: 8px;
          padding: 8px 0;
          
          .info-item {
            display: flex;
            gap: 4px;
            
            .info-label {
              color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
              font-weight: 500;
              white-space: nowrap;
              &::after {
                content: '：';
              }
            }
            
            .info-value {
              color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
              word-break: break-word;
            }
          }
        }
        
        /* 反馈提示列表 */
        .feedback-tips-list {
          margin: 8px 0;
          
          li {
            margin-bottom: 8px;
            color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
            line-height: 1.5;
          }
        }
        
        /* 反馈步骤内容 */
        .feedback-steps-content {
          padding: 8px 0;
          color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
          line-height: 1.5;
        }
      }
    `
  }
}
